package com.test.common.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;


@Aspect
@Component
public class DoAspect {
	
	//参考文件 https://blog.csdn.net/wangmx1993328/article/details/108164388
	
    // @annotation()：针对否个注解来定义切面，如下根据@GetMapping进行切面 比如：@GetMapping、@PostMapping、@DeleteMapping
	// @Pointcut() 根据方法类匹配
	// @Pointcut("execution(* com.example.service.*.*(..))")

	@Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")
	public void pointCut() { 
		
	}
	
	// @Before：在之前做什么，指定的方法在切面切入目标方法之前执行
//	@Before("pointCut()")
//    public void before(JoinPoint joinPoint){
//		
////		Object getThis()：获取代理对象
////		Object getTarget()：获取被代理对象
////		Object[] getArgs()：获取目标方法的参数列表
////		Signature getSignature()：返回被增强的方法的相关信息（修饰符+包名+类名+方法名）
////		Object proceed() throws Throwable;
////		执行目标方法
////
////		Object proceed(Object[] var1) throws Throwable;
////		传入的新的参数去执行目标方法
//		
////		System.out.println( joinPoint.getTarget());
////		System.out.println( joinPoint.getThis());
////		System.out.println( joinPoint.getArgs());
////		System.out.println( joinPoint.getClass());
////		System.out.println( joinPoint.getKind());
////		System.out.println( joinPoint.getSignature());
////		System.out.println( joinPoint.getSourceLocation());
////		System.out.println( joinPoint.getStaticPart());
//        System.out.println("===========before===========");
//    }
	
	//切面中的一种通知类型，它允许在目标方法执行前后完全控制目标方法的执行。
	//可以决定是否继续执行目标方法，以及是否修改目标方法的输入参数和返回值
	//ProceedingJoinPoint is only supported for around advice
//	@Around("pointCut()")
//	public Object  around(ProceedingJoinPoint joinPoint) throws Throwable {
//		
//		  System.out.println("===========around===========");
//		  long startTime = System.currentTimeMillis();
//	        // 执行目标方法
//	        Object result = joinPoint.proceed();
//	        long endTime = System.currentTimeMillis();
//	        System.out.println(
//	                joinPoint.getSignature() + " executed in " + (endTime - startTime) + "ms");
//	        return result;
//	}
//	
//	@After：指定的方法在切面切入目标方法之后执行、和@Before注解对应
//	@After("pointCut()")
//    public void after(JoinPoint joinPoint){
//		System.out.println( joinPoint.getTarget());
//		System.out.println( joinPoint.getThis());
//		System.out.println( joinPoint.getArgs());
//		System.out.println( joinPoint.getClass());
//		System.out.println( joinPoint.getKind());
//		System.out.println( joinPoint.getSignature());
//		System.out.println( joinPoint.getSourceLocation());
//		System.out.println( joinPoint.getStaticPart());
//		System.out.println("===========after===========");
//    }
//	
//	    @AfterReturning ：和 `@After` 有些类似，区别在于 `@AfterReturning` 注解可以用来捕获切入方法执行完之后的返回值，对返回值进行业务逻辑上的增强处理
//	    pointcut：切面方法名
//	    returning:被切方法的返回值，必须要和参数保持一致，否则会检测不到
//		@AfterReturning(pointcut = "pointCut()", returning = "result")
//	    public void afterReturning(JoinPoint joinPoint,Object result) {
//			System.out.println("结果为"+result);
//			System.out.println("===========afterReturning===========");
//	    }
	
//     @AfterThrowing：被切方法执行时抛出异常时会进入
//     pointcut：切面方法名
//     throwing：属性的值必须要和参数一致
//	 @AfterThrowing(pointcut = "pointCut()", throwing = "ex")
//	    public void afterThrowing(JoinPoint joinPoint,Throwable ex) {
//		 System.out.println("===========afterThrowing===========");
//		  String methodName = joinPoint.getSignature().getName();
//	        if (ex instanceof ArithmeticException) {
//	           System.out.println("【异常通知】" + methodName + "方法算术异常（ArithmeticException）：" + ex.getMessage());
//	        } else {
//	        	 System.out.println("【异常通知】" + methodName + "方法异常：" + ex.getMessage());
//		 
//	    }
//	 }
}
